package com.example.job.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.core.constants.CacheConstants;
import com.example.common.core.enums.ExamListType;
import com.example.common.redis.RedisService;
import com.example.job.domain.Exam;
import com.example.job.domain.ExamVO;
import com.example.job.mapper.ExamMapper;
import com.example.job.mapper.UserExamMapper;
import jakarta.annotation.Resource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author 23050
 * @version 1.0
 * @description:
 * @date 2025/3/10 20:00
 */
@Component
public class ScheduleTasks {

    @Resource
    private ExamMapper examMapper;

    @Resource
    private RedisService redisService;

    @Resource
    private UserExamMapper userExamMapper;



    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    /**
     * @author 23050
     * @description:  刷新未完赛、历史竞赛、个人报名竞赛的Redis缓存
     * @date: 2025/3/26 22:00
     * @return void
     */
    // 使用 @Scheduled 注解，指定 Cron 表达式
//    @Scheduled(cron = "0 0 1 * * ?")   //每天凌晨1点执行
    @Scheduled(cron = "0/10 * * * * ?")   //每十秒执行
    public void performTask() {
        System.out.println("定时任务执行，当前时间：" + dateFormat.format(new Date()));



        //刷新未完赛的redis
        System.out.println("---------------刷新未完赛list");
        refreshCache(ExamListType.EXAM_UN_FINISH_LIST.getValue(),null);


        //刷新历史竞赛的redis
        System.out.println("-------------- 刷新历史竞赛list");
        refreshCache(ExamListType.EXAM_HISTORY_LIST.getValue(),null);


        //刷新用户个人竞赛的redis
        System.out.println("-------------- 刷新用户报名竞赛list");
        //获取所有用户id，全部更新
        List<Long> userIdList = userExamMapper.selectDistinctUserIds();
        //刷新所有用户报名的竞赛列表
        for (Long userId:userIdList){
            refreshCache(ExamListType.USER_EXAM_LIST.getValue(),userId);
        }
    }



    //刷新redis
    public void refreshCache(Integer examListType,Long userId) {
        List<Exam> examList = new ArrayList<>();
        if (ExamListType.EXAM_UN_FINISH_LIST.getValue().equals(examListType)) {
            //查询未完赛的竞赛列表
            examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                    .select(Exam::getExamId, Exam::getTitle, Exam::getStartTime, Exam::getEndTime)
                    .gt(Exam::getEndTime, LocalDateTime.now())
                    .eq(Exam::getStatus, 1)
                    .orderByDesc(Exam::getStartTime));
        } else if (ExamListType.EXAM_HISTORY_LIST.getValue().equals(examListType)) {
            //查询历史竞赛
            examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                    .select(Exam::getExamId, Exam::getTitle, Exam::getStartTime, Exam::getEndTime)
                    .le(Exam::getEndTime, LocalDateTime.now())
                    .eq(Exam::getStatus, 1)
                    .orderByDesc(Exam::getStartTime));
        }else if (ExamListType.USER_EXAM_LIST.getValue().equals(examListType)){
            //查询用户报名竞赛
            List<ExamVO> examVOList = userExamMapper.selectUserExamList(userId);
            //使用hutu工具类，将examVO的list复制到exam的list
            examList = BeanUtil.copyToList(examVOList, Exam.class);
        }
//        System.out.println("数据库中的数据："+examList.size());
//        System.out.println(examList);
        //判断数据库里是否有数据
        if (CollectionUtil.isEmpty(examList)) {
            redisService.deleteObject(getExamListKey(examListType,userId));
            return;
        }

        //将拿到的数据放到redis中
        Map<String, Exam> examMap = new HashMap<>();  //exam:detail:examId - exam详情
        List<Long> examIdList = new ArrayList<>();  //用于刷新未完赛和历史竞赛的数据
        for (Exam exam : examList) {
            examMap.put(getDetailKey(exam.getExamId()), exam);
            examIdList.add(exam.getExamId());
        }
        //批量的将竞赛详情存到redis中 exam:detail:examId:竞赛详情
        redisService.multiSet(examMap);  //刷新详情缓存
        //删除未完赛或历史竞赛列表或用户报名竞赛的列表  然后重新存储
        redisService.deleteObject(getExamListKey(examListType,userId));
        redisService.rightPushAll(getExamListKey(examListType,userId), examIdList);      //刷新列表缓存
    }


    private String getDetailKey(Long examId) {
        return CacheConstants.EXAM_DETAIL + examId;
    }


    //拼接当前访问的是未完赛列表还是历史竞赛列表的key
    private String getExamListKey(Integer examListType,Long userId) {
        if (ExamListType.EXAM_UN_FINISH_LIST.getValue().equals(examListType)) {
            return CacheConstants.EXAM_UNFINISHED_LIST;
        } else if (ExamListType.EXAM_HISTORY_LIST.getValue().equals(examListType)) {
            return CacheConstants.EXAM_HISTORY_LIST;
        } else {
            return CacheConstants.USER_EXAM_LIST + userId;
        }
    }


}
